﻿#region Copyright (c) 2000-2013 Developer Express Inc.
/*
{*******************************************************************}
{                                                                   }
{       Developer Express .NET Component Library                    }
{                                                                   }
{                                                                   }
{       Copyright (c) 2000-2013 Developer Express Inc.              }
{       ALL RIGHTS RESERVED                                         }
{                                                                   }
{   The entire contents of this file is protected by U.S. and       }
{   International Copyright Laws. Unauthorized reproduction,        }
{   reverse-engineering, and distribution of all or any portion of  }
{   the code contained in this file is strictly prohibited and may  }
{   result in severe civil and criminal penalties and will be       }
{   prosecuted to the maximum extent possible under the law.        }
{                                                                   }
{   RESTRICTIONS                                                    }
{                                                                   }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES           }
{   ARE CONFIDENTIAL AND PROPRIETARY TRADE                          }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS   }
{   LICENSED TO DISTRIBUTE THE PRODUCT AND ALL ACCOMPANYING .NET    }
{   CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY.                 }
{                                                                   }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED      }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE        }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE       }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                      }
{                                                                   }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON       }
{   ADDITIONAL RESTRICTIONS.                                        }
{                                                                   }
{*******************************************************************}
*/
#endregion Copyright (c) 2000-2013 Developer Express Inc.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Data;
namespace UColor.Core.Helpers {
	public static class IsMouseOverHelper {
		#region Dependency Properties
		public static readonly DependencyProperty EnableIsMouseOverProperty;
		public static readonly DependencyProperty IsMouseOverProperty;
#if SL
		static readonly DependencyProperty IsHitTestVisibleListenProperty;
#endif
		static IsMouseOverHelper() {
			Type ownerType = typeof(IsMouseOverHelper);
			EnableIsMouseOverProperty = DependencyProperty.RegisterAttached("EnableIsMouseOver", typeof(object), ownerType, new PropertyMetadata(null, RaiseEnableIsMouseOverChanged));
			IsMouseOverProperty = DependencyProperty.RegisterAttached("IsMouseOver", typeof(bool), ownerType, new PropertyMetadata(false, RaiseIsMouseOverChanged));
#if SL
			IsHitTestVisibleListenProperty = DependencyProperty.RegisterAttached("IsHitTestVisibleListen", typeof(bool), ownerType, new PropertyMetadata(true, RaiseIsHitTestVisibleListenChanged));
#endif
		}
		#endregion
		public static object GetEnableIsMouseOver(UIElement e) { return e.GetValue(EnableIsMouseOverProperty); }
		public static void SetEnableIsMouseOver(UIElement e, object v) { e.SetValue(EnableIsMouseOverProperty, v); }
		public static bool GetIsMouseOver(UIElement e) { return (bool)e.GetValue(IsMouseOverProperty); }
		public static void SetIsMouseOver(UIElement e, bool v) { e.SetValue(IsMouseOverProperty, v); }
		static void RaiseIsMouseOverChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			UIElement element = (UIElement)d;
			Action<bool> onIsMouseOverChanged = GetEnableIsMouseOver(element) as Action<bool>;
			if(onIsMouseOverChanged != null)
				onIsMouseOverChanged((bool)e.NewValue);
		}
		static void RaiseEnableIsMouseOverChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			UIElement element = (UIElement)d;
			if(e.NewValue != null) {
				element.LostMouseCapture += OnElementLostMouseCapture;
				element.MouseEnter += OnElementMouseEnter;
				element.MouseLeave += OnElementMouseLeave;
#if SL
				BindingOperations.SetBinding(element, IsHitTestVisibleListenProperty, new Binding("IsHitTestVisible") { Source = element, Mode = BindingMode.OneWay });
#else
				element.IsHitTestVisibleChanged += OnIsHitTestVisibleChanged;
#endif
			} else {
				element.LostMouseCapture -= OnElementLostMouseCapture;
				element.MouseEnter -= OnElementMouseEnter;
				element.MouseLeave -= OnElementMouseLeave;
#if SL
				element.ClearValue(IsHitTestVisibleListenProperty);
#else
				element.IsHitTestVisibleChanged -= OnIsHitTestVisibleChanged;
#endif
			}
		}
		static void OnElementMouseLeave(object sender, MouseEventArgs e) {
			UIElement element = (UIElement)sender;
			SetIsMouseOver(element, false);
		}
		static void OnElementMouseEnter(object sender, MouseEventArgs e) {
			UIElement element = (UIElement)sender;
			SetIsMouseOver(element, true);
		}
		static void OnElementLostMouseCapture(object sender, MouseEventArgs e) {
			UIElement element = (UIElement)sender;
			SetIsMouseOver(element, false);
		}
#if SL
		static void RaiseIsHitTestVisibleListenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			OnIsHitTestVisibleChanged(d, e);
		}
#endif
		static void OnIsHitTestVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) {
			UIElement element = (UIElement)sender;
			if(!(bool)e.NewValue)
				SetIsMouseOver(element, false);
		}
	}
	public enum ButtonCommonState { Normal, MouseOver, Pressed, Disabled }
	public class ButtonExt : Button {
		#region Dependency Properties
		public static readonly DependencyProperty CommonStateProperty;
		static readonly DependencyProperty VisibilityListenProperty;
		static ButtonExt() {
			Type ownerType = typeof(ButtonExt);
			CommonStateProperty = DependencyProperty.Register("CommonState", typeof(ButtonCommonState), ownerType, new PropertyMetadata(ButtonCommonState.Normal, RaiseCommonStateChanged));
			VisibilityListenProperty = DependencyProperty.Register("VisibilityListen", typeof(Visibility), ownerType, new PropertyMetadata(Visibility.Collapsed, RaiseVisibilityListenChanged));
		}
		ButtonCommonState commonStateValue = ButtonCommonState.Normal;
		static void RaiseCommonStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ButtonExt)d).commonStateValue = (ButtonCommonState)e.NewValue;
		}
		static void RaiseVisibilityListenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ButtonExt)d).RaiseVisibilityChanged(e);
		}
		#endregion
		bool isMouseOver = false;
		public ButtonExt() {
			SetBinding(VisibilityListenProperty, new Binding("Visibility") { Source = this, Mode = BindingMode.OneWay });
			IsEnabledChanged += OnIsEnabledChanged;
			IsMouseOverHelper.SetEnableIsMouseOver(this, (Action<bool>)OnIsMouseOverChanged);
		}
		public event DepPropertyChangedEventHandler VisibilityChanged;
		public ButtonCommonState CommonState { get { return commonStateValue; } private set { SetValue(CommonStateProperty, value); } }
		void OnIsMouseOverChanged(bool isMouseOver) {
			this.isMouseOver = isMouseOver;
			UpdateStates();
		}
		protected virtual void RaiseVisibilityChanged(DependencyPropertyChangedEventArgs e) {
			if(VisibilityChanged != null)
				VisibilityChanged(this, new DepPropertyChangedEventArgs(e));
		}
		protected override void OnIsPressedChanged(DependencyPropertyChangedEventArgs e) {
			base.OnIsPressedChanged(e);
			UpdateStates();
		}
		void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) {
			UpdateStates();
		}
		void UpdateStates() {
			if(!IsEnabled) {
				CommonState = ButtonCommonState.Disabled;
			} else if(IsPressed) {
				CommonState = ButtonCommonState.Pressed;
			} else if(isMouseOver) {
				CommonState = ButtonCommonState.MouseOver;
			} else {
				CommonState = ButtonCommonState.Normal;
			}
		}
	}
	public enum ListBoxItemCommonState { Normal, MouseOver, Disabled }
	public enum ListBoxItemSelectionState { Unselected, MouseOverUnselected, Selected, MouseOverSelected }
	public class ListBoxItemExt : ListBoxItem {
		#region Dependency Properties
		public static readonly DependencyProperty CommonStateProperty;
		public static readonly DependencyProperty SelectionStateProperty;
		static readonly DependencyProperty VisibilityListenProperty;
		static readonly DependencyProperty IsSelectedListenProperty;
		static ListBoxItemExt() {
			Type ownerType = typeof(ListBoxItemExt);
			CommonStateProperty = DependencyProperty.Register("CommonState", typeof(ListBoxItemCommonState), ownerType, new PropertyMetadata(ListBoxItemCommonState.Normal, RaiseCommonStateChanged));
			SelectionStateProperty = DependencyProperty.Register("SelectionState", typeof(ListBoxItemSelectionState), ownerType, new PropertyMetadata(ListBoxItemSelectionState.Unselected, RaiseSelectionStateChanged));
			VisibilityListenProperty = DependencyProperty.Register("VisibilityListen", typeof(Visibility), ownerType, new PropertyMetadata(Visibility.Collapsed, RaiseVisibilityListenChanged));
			IsSelectedListenProperty = DependencyProperty.Register("IsSelectedListen", typeof(bool), ownerType, new PropertyMetadata(false, RaiseIsSelectedListenChanged));
		}
		ListBoxItemCommonState commonStateValue = ListBoxItemCommonState.Normal;
		ListBoxItemSelectionState selectionStateValue = ListBoxItemSelectionState.Unselected;
		static void RaiseCommonStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ListBoxItemExt)d).commonStateValue = (ListBoxItemCommonState)e.NewValue;
		}
		static void RaiseSelectionStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ListBoxItemExt)d).selectionStateValue = (ListBoxItemSelectionState)e.NewValue;
		}
		static void RaiseVisibilityListenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ListBoxItemExt)d).RaiseVisibilityChanged(e);
		}
		static void RaiseIsSelectedListenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
			((ListBoxItemExt)d).RaiseIsSelectedChanged(e);
		}
		#endregion
		bool isMouseOver = false;
		public ListBoxItemExt() {
			SetBinding(VisibilityListenProperty, new Binding("Visibility") { Source = this, Mode = BindingMode.OneWay });
			SetBinding(IsSelectedListenProperty, new Binding("IsSelected") { Source = this, Mode = BindingMode.OneWay });
			IsEnabledChanged += OnIsEnabledChanged;
			IsMouseOverHelper.SetEnableIsMouseOver(this, (Action<bool>)OnIsMouseOverChanged);
		}
		public event DepPropertyChangedEventHandler VisibilityChanged;
		public event DepPropertyChangedEventHandler IsSelectedChanged;
		public ListBoxItemCommonState CommonState { get { return commonStateValue; } private set { SetValue(CommonStateProperty, value); } }
		public ListBoxItemSelectionState SelectionState { get { return selectionStateValue; } private set { SetValue(SelectionStateProperty, value); } }
		protected virtual void RaiseVisibilityChanged(DependencyPropertyChangedEventArgs e) {
			if(VisibilityChanged != null)
				VisibilityChanged(this, new DepPropertyChangedEventArgs(e));
		}
		void OnIsMouseOverChanged(bool isMouseOver) {
			this.isMouseOver = isMouseOver;
			UpdateStates();
		}
		void RaiseIsSelectedChanged(DependencyPropertyChangedEventArgs e) {
			if(IsSelectedChanged != null)
				IsSelectedChanged(this, new DepPropertyChangedEventArgs(e));
			UpdateStates();
		}
		void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) {
			UpdateStates();
		}
		void UpdateStates() {
			if(!IsEnabled) {
				CommonState = ListBoxItemCommonState.Disabled;
			} else if(isMouseOver) {
				CommonState = ListBoxItemCommonState.MouseOver;
			} else {
				CommonState = ListBoxItemCommonState.Normal;
			}
			if(IsSelected) {
				if(isMouseOver) {
					SelectionState = ListBoxItemSelectionState.MouseOverSelected;
				} else {
					SelectionState = ListBoxItemSelectionState.Selected;
				}
			} else {
				if(isMouseOver) {
					SelectionState = ListBoxItemSelectionState.MouseOverUnselected;
				} else {
					SelectionState = ListBoxItemSelectionState.Unselected;
				}
			}
		}
	}
	public class ListBoxEx : ListBox {
		protected override DependencyObject GetContainerForItemOverride() {
			return new ListBoxItemExt();
		}
	}
}
